/**
 ******************************************************************************
 * @file           : bsp_rs485_config.h
 * @brief          : RS485 Configuration File (STM32F1xx)
 ******************************************************************************
 * @attention
 *
 * RS485硬件配置文件
 * 包含引脚定义、UART配置等硬件相关参数
 * 用户根据实际硬件修改此文件
 *
 ******************************************************************************
 */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __BSP_RS485_CONFIG_H
#define __BSP_RS485_CONFIG_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx.h"

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/

/* ============================================================================ */
/*                          依赖配置（移植时修改这里）                            */
/* ============================================================================ */

/**
 * 延时函数配置
 * 
 * RS485需要毫秒级延时函数（用于发送后切换方向）：
 * 
 * 方案1：使用HAL库（默认推荐）
 *   #define RS485_DELAY_MS(ms)  HAL_Delay(ms)
 * 
 * 方案2：使用RTOS延时
 *   #include "cmsis_os.h"
 *   #define RS485_DELAY_MS(ms)  osDelay(ms)
 * 
 * 方案3：使用自定义延时
 *   #include "your_delay.h"
 *   #define RS485_DELAY_MS(ms)  your_delay_ms(ms)
 */

/* 默认实现：使用HAL库延时 */
#ifndef RS485_DELAY_MS
    #define RS485_DELAY_MS(ms)  HAL_Delay(ms)
#endif

/* 用户可以在工程中预先定义RS485_DELAY_MS来覆盖默认实现 */

/* ============================================================================ */
/*                       日志系统配置（改这里的数字）                             */
/* ============================================================================ */
/* 日志后端选择：1=EasyLogger, 2=printf, 0=关闭 */
#define RS485_USE_LOG     1

/* 根据配置自动定义日志宏 */
#if (RS485_USE_LOG == 1)
    /* 使用EasyLogger */
    #ifndef LOG_TAG
        #define LOG_TAG    "RS485"
    #endif
    #include "elog.h"
    
#elif (RS485_USE_LOG == 2)
    /* 使用printf */
    #include <stdio.h>
    #define log_i(fmt, ...)     printf(fmt "\r\n", ##__VA_ARGS__)
    #define log_w(fmt, ...)     printf("[WARN] " fmt "\r\n", ##__VA_ARGS__)
    #define log_e(fmt, ...)     printf("[ERROR] " fmt "\r\n", ##__VA_ARGS__)
    #define log_d(fmt, ...)     printf("[DEBUG] " fmt "\r\n", ##__VA_ARGS__)
    
#else
    /* 关闭日志 */
    #define log_i(fmt, ...)
    #define log_w(fmt, ...)
    #define log_e(fmt, ...)
    #define log_d(fmt, ...)
#endif

/* ============================================================================ */
/*                      串口选择配置（改这里即可切换串口）                         */
/* ============================================================================ */
/**
 * @brief 串口选择（1=USART1, 2=USART2, 3=USART3, 4=UART4, 5=UART5）
 * 
 * 修改此值即可切换RS485使用的串口，引脚和外设配置会自动更改
 * 支持的串口及默认引脚：
 *   USART1: TX=PA9,  RX=PA10  (支持重映射到 PB6/PB7)
 *   USART2: TX=PA2,  RX=PA3   (支持重映射到 PD5/PD6)
 *   USART3: TX=PB10, RX=PB11  (支持重映射到 PC10/PC11 或 PD8/PD9)
 *   UART4:  TX=PC10, RX=PC11
 *   UART5:  TX=PC12, RX=PD2
 */
#define RS485_USART_SELECT_NUM          1       /*!< 选择使用的串口号 */

/**
 * @brief 引脚重映射配置（仅USART1/2/3支持）
 * 
 * 0 = 不重映射（使用默认引脚）
 * 1 = 部分重映射（USART1/3）或完全重映射（USART2）
 * 2 = 完全重映射（仅USART3）
 */
#define RS485_USART_REMAP_MODE          0       /*!< 引脚重映射模式 */

/**
 * @brief RS485方向控制引脚（RE/DE）
 * 
 * 此引脚独立配置，不随串口选择改变
 * 连接到RS485收发器的RE和DE引脚（通常短接在一起）
 * - RE=0: 接收模式
 * - RE=1: 发送模式
 */
#define RS485_RE_GPIO_PORT              GPIOA                                           /*!< RE控制引脚端口 */
#define RS485_RE_GPIO_PIN               GPIO_PIN_8                                      /*!< RE控制引脚号 */
#define RS485_RE_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)     /*!< RE端口时钟使能 */

/* ============================================================================ */
/*                    自动配置区域（请勿手动修改）                                */
/* ============================================================================ */

/* --------------------------------------------------------------------------- */
/* USART1 配置 (PA9/PA10 或 PB6/PB7)                                            */
/* --------------------------------------------------------------------------- */
#if (RS485_USART_SELECT_NUM == 1)
    #define RS485_UARTx                     USART1
    #define RS485_UARTx_IRQn                USART1_IRQn
    #define RS485_UARTx_CLK_ENABLE()        do{ __HAL_RCC_USART1_CLK_ENABLE(); }while(0)
    #define RS485_USARTx_IRQHandler         USART1_IRQHandler
    
    #if (RS485_USART_REMAP_MODE == 1)  /* 重映射到PB6/PB7 */
        #define RS485_TX_GPIO_PORT              GPIOB
        #define RS485_TX_GPIO_PIN               GPIO_PIN_6
        #define RS485_TX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)
        
        #define RS485_RX_GPIO_PORT              GPIOB
        #define RS485_RX_GPIO_PIN               GPIO_PIN_7
        #define RS485_RX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)
        
        #define RS485_GPIO_REMAP_CONFIG()       do{ __HAL_AFIO_REMAP_USART1_ENABLE(); }while(0)
    #else  /* 默认PA9/PA10 */
        #define RS485_TX_GPIO_PORT              GPIOA
        #define RS485_TX_GPIO_PIN               GPIO_PIN_9
        #define RS485_TX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)
        
        #define RS485_RX_GPIO_PORT              GPIOA
        #define RS485_RX_GPIO_PIN               GPIO_PIN_10
        #define RS485_RX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)
        
        #define RS485_GPIO_REMAP_CONFIG()       /* 不需要重映射 */
    #endif

/* --------------------------------------------------------------------------- */
/* USART2 配置 (PA2/PA3 或 PD5/PD6)                                             */
/* --------------------------------------------------------------------------- */
#elif (RS485_USART_SELECT_NUM == 2)
    #define RS485_UARTx                     USART2
    #define RS485_UARTx_IRQn                USART2_IRQn
    #define RS485_UARTx_CLK_ENABLE()        do{ __HAL_RCC_USART2_CLK_ENABLE(); }while(0)
    #define RS485_USARTx_IRQHandler         USART2_IRQHandler
    
    #if (RS485_USART_REMAP_MODE == 1)  /* 重映射到PD5/PD6 */
        #define RS485_TX_GPIO_PORT              GPIOD
        #define RS485_TX_GPIO_PIN               GPIO_PIN_5
        #define RS485_TX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0)
        
        #define RS485_RX_GPIO_PORT              GPIOD
        #define RS485_RX_GPIO_PIN               GPIO_PIN_6
        #define RS485_RX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0)
        
        #define RS485_GPIO_REMAP_CONFIG()       do{ __HAL_AFIO_REMAP_USART2_ENABLE(); }while(0)
    #else  /* 默认PA2/PA3 */
        #define RS485_TX_GPIO_PORT              GPIOA
        #define RS485_TX_GPIO_PIN               GPIO_PIN_2
        #define RS485_TX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)
        
        #define RS485_RX_GPIO_PORT              GPIOA
        #define RS485_RX_GPIO_PIN               GPIO_PIN_3
        #define RS485_RX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)
        
        #define RS485_GPIO_REMAP_CONFIG()       /* 不需要重映射 */
    #endif

/* --------------------------------------------------------------------------- */
/* USART3 配置 (PB10/PB11 或 PC10/PC11 或 PD8/PD9)                              */
/* --------------------------------------------------------------------------- */
#elif (RS485_USART_SELECT_NUM == 3)
    #define RS485_UARTx                     USART3
    #define RS485_UARTx_IRQn                USART3_IRQn
    #define RS485_UARTx_CLK_ENABLE()        do{ __HAL_RCC_USART3_CLK_ENABLE(); }while(0)
    #define RS485_USARTx_IRQHandler         USART3_IRQHandler
    
    #if (RS485_USART_REMAP_MODE == 1)  /* 部分重映射到PC10/PC11 */
        #define RS485_TX_GPIO_PORT              GPIOC
        #define RS485_TX_GPIO_PIN               GPIO_PIN_10
        #define RS485_TX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)
        
        #define RS485_RX_GPIO_PORT              GPIOC
        #define RS485_RX_GPIO_PIN               GPIO_PIN_11
        #define RS485_RX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)
        
        #define RS485_GPIO_REMAP_CONFIG()       do{ __HAL_AFIO_REMAP_USART3_PARTIAL(); }while(0)
    #elif (RS485_USART_REMAP_MODE == 2)  /* 完全重映射到PD8/PD9 */
        #define RS485_TX_GPIO_PORT              GPIOD
        #define RS485_TX_GPIO_PIN               GPIO_PIN_8
        #define RS485_TX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0)
        
        #define RS485_RX_GPIO_PORT              GPIOD
        #define RS485_RX_GPIO_PIN               GPIO_PIN_9
        #define RS485_RX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0)
        
        #define RS485_GPIO_REMAP_CONFIG()       do{ __HAL_AFIO_REMAP_USART3_ENABLE(); }while(0)
    #else  /* 默认PB10/PB11 */
        #define RS485_TX_GPIO_PORT              GPIOB
        #define RS485_TX_GPIO_PIN               GPIO_PIN_10
        #define RS485_TX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)
        
        #define RS485_RX_GPIO_PORT              GPIOB
        #define RS485_RX_GPIO_PIN               GPIO_PIN_11
        #define RS485_RX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)
        
        #define RS485_GPIO_REMAP_CONFIG()       /* 不需要重映射 */
    #endif

/* --------------------------------------------------------------------------- */
/* UART4 配置 (PC10/PC11)                                                       */
/* --------------------------------------------------------------------------- */
#elif (RS485_USART_SELECT_NUM == 4)
    #define RS485_UARTx                     UART4
    #define RS485_UARTx_IRQn                UART4_IRQn
    #define RS485_UARTx_CLK_ENABLE()        do{ __HAL_RCC_UART4_CLK_ENABLE(); }while(0)
    #define RS485_USARTx_IRQHandler         UART4_IRQHandler
    
    #define RS485_TX_GPIO_PORT              GPIOC
    #define RS485_TX_GPIO_PIN               GPIO_PIN_10
    #define RS485_TX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)
    
    #define RS485_RX_GPIO_PORT              GPIOC
    #define RS485_RX_GPIO_PIN               GPIO_PIN_11
    #define RS485_RX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)
    
    #define RS485_GPIO_REMAP_CONFIG()       /* UART4不支持重映射 */

/* --------------------------------------------------------------------------- */
/* UART5 配置 (PC12/PD2)                                                        */
/* --------------------------------------------------------------------------- */
#elif (RS485_USART_SELECT_NUM == 5)
    #define RS485_UARTx                     UART5
    #define RS485_UARTx_IRQn                UART5_IRQn
    #define RS485_UARTx_CLK_ENABLE()        do{ __HAL_RCC_UART5_CLK_ENABLE(); }while(0)
    #define RS485_USARTx_IRQHandler         UART5_IRQHandler
    
    #define RS485_TX_GPIO_PORT              GPIOC
    #define RS485_TX_GPIO_PIN               GPIO_PIN_12
    #define RS485_TX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)
    
    #define RS485_RX_GPIO_PORT              GPIOD
    #define RS485_RX_GPIO_PIN               GPIO_PIN_2
    #define RS485_RX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0)
    
    #define RS485_GPIO_REMAP_CONFIG()       /* UART5不支持重映射 */

#else
    #error "RS485_USART_SELECT_NUM must be 1~5!"
#endif

/* ============================================================================ */
/*                          功能配置（用户可修改）                               */
/* ============================================================================ */

/* RS485缓冲区大小 */
#define RS485_RX_BUF_SIZE               128     /*!< 接收缓冲区大小(字节) */

/* RS485超时配置 */
#define RS485_TX_TIMEOUT                1000    /*!< 发送超时时间(ms) */
#define RS485_RX_TIMEOUT                100     /*!< 接收超时时间(ms) */

/* RS485默认波特率 */
#define RS485_DEFAULT_BAUDRATE          115200  /*!< 默认波特率 */

/* ============================================================================ */
/*                          高级配置（一般不需要修改）                           */
/* ============================================================================ */

/* RS485收发模式控制宏 */
#define RS485_TX_MODE()                 HAL_GPIO_WritePin(RS485_RE_GPIO_PORT, RS485_RE_GPIO_PIN, GPIO_PIN_SET)
#define RS485_RX_MODE()                 HAL_GPIO_WritePin(RS485_RE_GPIO_PORT, RS485_RE_GPIO_PIN, GPIO_PIN_RESET)

/* Exported macro ------------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/

#ifdef __cplusplus
}
#endif

#endif /* __BSP_RS485_CONFIG_H */
